package com.example.locationtracking.view;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;

import com.example.locationtracking.R;
import com.example.locationtracking.model.UserLocation;
import com.example.locationtracking.service.Service;
import com.example.locationtracking.service.impl.ServiceFactory;
import com.example.locationtracking.utils.Const;
import com.example.locationtracking.utils.LTUtils;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.internal.ca;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.GoogleMap.CancelableCallback;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;

public class LocationHistoryActivity extends BaseActivity implements
		ConnectionCallbacks, OnConnectionFailedListener {

	private GoogleMap mMap;
	private LocationClient mLocationClient;
	String userName = "";
	float []markerColors = new float[]{ BitmapDescriptorFactory.HUE_RED, BitmapDescriptorFactory.HUE_YELLOW, BitmapDescriptorFactory.HUE_GREEN, BitmapDescriptorFactory.HUE_BLUE};
	List<Marker>markers = new ArrayList<Marker>();
	protected void initUI() {
		if (!LTUtils.checkInternetConnection(this)) {
			Intent intent = new Intent(this, NetWorkErrorActivity.class);
			intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
			startActivityForResult(intent, Const.NETWORK_ACTIVITY_REQUEST_CODE);
			finish();
			return;
		}
		setContentView(R.layout.location_history_activity);
		userName = getIntent().getStringExtra(Const.USER_NAME_KEY);

		if (!LTUtils.checkLocationService(this))
			showLocationSettingDlg(R.string.msg_location_not_enabled);

		createMapIfReady();
		setUpLocationClientIfNeeded();
		mLocationClient.connect();
		loadHistoryLoactionList();
		setTitle(userName);
	}

	// These settings are the same as the settings for the map. They will in
	// fact give you updates

	private void createMapIfReady() {
		// Do a null check to confirm that we have not already instantiated the
		// map.
		if (mMap == null) {
			// Try to obtain the map from the SupportMapFragment.
			SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
					.findFragmentById(R.id.map);
			mMap = mapFragment.getMap();
			if (mMap != null) {
				mMap.setMyLocationEnabled(false);
			}
		}
	}

	private void setUpLocationClientIfNeeded() {
		if (mLocationClient == null) {
			mLocationClient = new LocationClient(getApplicationContext(), this, // ConnectionCallbacks
					this); // OnConnectionFailedListener
		}
	}

	@Override
	public void onPause() {
		super.onPause();
		if (mLocationClient != null) {
			mLocationClient.disconnect();
		}
	}

	@Override
	public void onResume() {
		super.onResume();

		int resultCode = GooglePlayServicesUtil
				.isGooglePlayServicesAvailable(getApplicationContext());

		if (resultCode == ConnectionResult.SUCCESS) {
			/*
			 * Toast.makeText(getApplicationContext(),
			 * "isGooglePlayServicesAvailable SUCCESS",
			 * Toast.LENGTH_LONG).show();
			 */
		} else {
			GooglePlayServicesUtil.getErrorDialog(resultCode, this,
					Const.RQS_GooglePlayServices).show();
		}

	}

	@Override
	public void onConnectionFailed(ConnectionResult result) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onConnected(Bundle connectionHint) {

	}

	@Override
	public void onDisconnected() {
		// TODO Auto-generated method stub

	}

	/**
	 * Change the camera position by moving or animating the camera depending on
	 * the state of the animate toggle button.
	 */
	private void loadHistoryLoactionList() {
		if (!userName.isEmpty()) {
			Thread thread = new Thread(new Runnable() {

				@Override
				public void run() {
					Message msg = handler.obtainMessage();
					Service service = ServiceFactory.getInstance().getService();
					try {
						List<UserLocation> userLocations = service
								.getHistoryLocationUserList(userName);
						msg.obj = userLocations;
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
						handler.sendMessage(msg);
					
				}
			});
			showProgressDlg();
			thread.start();
		}
	}

	@SuppressLint("HandlerLeak")
	private Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			dismissProgressDlg();
			if (msg.obj != null) {
				@SuppressWarnings("unchecked")
				List<UserLocation> userLocations = (List<UserLocation>) msg.obj;
				if (userLocations.isEmpty()){
					Toast.makeText(getApplicationContext(), "There isn't history!",
							Toast.LENGTH_SHORT).show();
					return;
				}
				
				drawLocation(userLocations);
				markers.get(0).showInfoWindow();
				changeCamera(markers.get(0).getPosition(), userName);
			} else {
				Toast.makeText(getApplicationContext(), "There isn't history!",
						Toast.LENGTH_SHORT).show();
			}
		}
	};
	/**
	 * Change the camera position by moving or animating the camera depending on
	 * the state of the animate toggle button.
	 */

	private void changeCamera(final LatLng currLng, final String userName) {
		CameraPosition currPos = new CameraPosition.Builder().target(currLng)
				.zoom(15.5f).bearing(0).tilt(25).build();
		mMap.animateCamera(CameraUpdateFactory.newCameraPosition(currPos),
				new CancelableCallback() {
					@Override
					public void onFinish() {
						
					}

					@Override
					public void onCancel() {
						// Toast.makeText(getBaseContext(),
						// "Animation to Sydney canceled",
						// Toast.LENGTH_SHORT).show();
					}
				});

	}
	private void drawLocation(List<UserLocation>locations){
		PolylineOptions line = new PolylineOptions();
		Collections.reverse(locations);
		Calendar calendar = Calendar.getInstance();
		UserLocation firstUser = locations.get(0);
		calendar.setTime(firstUser.getDateTime());
		int firstDay = calendar.get(Calendar.DAY_OF_YEAR);
		//draw first user
		LatLng currLng = new LatLng(Double.parseDouble(firstUser
				.getLatitude()), Double.parseDouble(firstUser
				.getLongitude()));
		MarkerOptions mk = new MarkerOptions();

		mk.position(currLng);
		mk.draggable(false);
		mk.title(firstUser.getTime());
		mk.icon(BitmapDescriptorFactory.defaultMarker(markerColors[0]));
		markers.add( mMap.addMarker(mk));
		line.add(currLng);
		//draw another user
		for(int i=1;i<locations.size();i++){
			UserLocation location = locations.get(i);
			calendar.setTime(location.getDateTime());
			int diffDay = firstDay - calendar.get(Calendar.DAY_OF_YEAR);
			if(diffDay>=markerColors.length)
				diffDay = markerColors.length-1;
			if(diffDay<0)
				diffDay=0;
			
			currLng = new LatLng(Double.parseDouble(location
					.getLatitude()), Double.parseDouble(location
					.getLongitude()));
			mk = new MarkerOptions();

			mk.position(currLng);
			mk.draggable(false);
			mk.title(location.getTime());
			mk.icon(BitmapDescriptorFactory.defaultMarker(markerColors[diffDay]));
			markers.add(mMap.addMarker(mk));
			line.add(currLng);
		}
		
		line.width(5).color(Color.RED);
		mMap.addPolyline(line);
		
	}
}
